#!/usr/bin/env node

/**
 * 瓦片图片标记工具
 * 功能：将指定XYZ瓦片目录中的图片添加Z/X/Y路径信息
 */

const fs = require('fs');
const path = require('path');
const process = require('process');

// 我们需要使用一个图片处理库，这里使用sharp，它是一个高性能的Node.js图片处理库
const sharp = require('sharp');

/**
 * 解析命令行参数
 */
function parseArguments() {
    const args = process.argv.slice(2);
    const options = {
        input: null,
        help: false
    };
    
    // 简单的命令行参数解析
    for (let i = 0; i < args.length; i++) {
        const arg = args[i];
        if (arg === '-i' || arg === '--input') {
            options.input = args[++i];
        } else if (arg === '-h' || arg === '--help') {
            options.help = true;
        }
    }
    
    return options;
}

/**
 * 显示帮助信息
 */
function showHelp() {
    console.log('========================================');
    console.log('瓦片图片标记工具 v1.0');
    console.log('========================================');
    console.log('用法: node addTileInfoToImages.js -i <瓦片目录>');
    console.log('');
    console.log('选项:');
    console.log('  -i, --input <目录>  指定XYZ瓦片目录路径');
    console.log('  -h, --help          显示此帮助信息');
    console.log('');
    console.log('示例:');
    console.log('  node addTileInfoToImages.js -i ./tiles');
    console.log('');
    console.log('说明:');
    console.log('  1. 工具会遍历指定目录下的所有XYZ格式瓦片');
    console.log('  2. 在每个瓦片图片上半部分添加红色文字标记');
    console.log('  3. 标记内容为瓦片的Z/X/Y坐标');
    console.log('  4. 文字大小会根据图片宽度自动调整');
    console.log('');
    console.log('注意:');
    console.log('  - 此工具会直接修改原始图片文件');
    console.log('  - 请确保在使用前备份重要数据');
    console.log('  - 仅支持PNG格式的瓦片图片');
}

/**
 * 检查依赖
 */
function checkDependencies() {
    try {
        // 尝试加载sharp库
        const sharp = require('sharp');
        
        // 检查sharp库是否可用
        if (typeof sharp !== 'function') {
            console.error('错误: sharp库已安装但不可用');
            return false;
        }
        
        return true;
    } catch (error) {
        console.error('错误: 缺少必要的依赖 sharp');
        console.error('请运行以下命令安装依赖:');
        console.error('  npm install sharp');
        console.error('');
        console.error('安装可能需要的系统依赖:');
        console.error('  Windows: 通常不需要额外依赖');
        console.error('  macOS: brew install vips');
        console.error('  Linux: apt-get install libvips-dev');
        return false;
    }
}

/**
 * 遍历瓦片目录并处理图片
 */
async function processTileDirectory(tileDir) {
    try {
        if (!fs.existsSync(tileDir)) {
            console.error(`错误: 目录不存在: ${tileDir}`);
            return false;
        }
        
        // 读取zoom目录
        console.log(`开始扫描瓦片目录: ${tileDir}`);
        let zoomDirs;
        try {
            zoomDirs = fs.readdirSync(tileDir)
                .filter(file => {
                    try {
                        const filePath = path.join(tileDir, file);
                        return fs.statSync(filePath).isDirectory() && /^\d+$/.test(file);
                    } catch (error) {
                        console.warn(`警告: 无法访问目录 ${file}: ${error.message}`);
                        return false;
                    }
                });
        } catch (error) {
            console.error(`错误: 无法读取目录内容: ${error.message}`);
            return false;
        }
        
        console.log(`找到 ${zoomDirs.length} 个缩放级别目录`);
        
        let processedCount = 0;
        let failedCount = 0;
        const startTime = Date.now();
        
        // 遍历每个zoom级别
        for (const zoom of zoomDirs) {
            const zoomPath = path.join(tileDir, zoom);
            console.log(`处理缩放级别 ${zoom}...`);
            
            // 读取x目录
            let xDirs;
            try {
                xDirs = fs.readdirSync(zoomPath)
                    .filter(file => {
                        try {
                            const filePath = path.join(zoomPath, file);
                            return fs.statSync(filePath).isDirectory() && /^\d+$/.test(file);
                        } catch (error) {
                            console.warn(`警告: 无法访问目录 ${zoom}/${file}: ${error.message}`);
                            return false;
                        }
                    });
                console.log(`  找到 ${xDirs.length} 个X坐标目录`);
            } catch (error) {
                console.error(`错误: 无法读取缩放级别 ${zoom} 内容: ${error.message}`);
                continue;
            }
            
            // 遍历每个x目录
            for (const x of xDirs) {
                const xPath = path.join(zoomPath, x);
                
                // 读取y图片文件
                let yFiles;
                try {
                    yFiles = fs.readdirSync(xPath)
                        .filter(file => {
                            try {
                                const filePath = path.join(xPath, file);
                                return fs.statSync(filePath).isFile() && /^\d+\.png$/.test(file);
                            } catch (error) {
                                console.warn(`警告: 无法访问文件 ${zoom}/${x}/${file}: ${error.message}`);
                                return false;
                            }
                        });
                } catch (error) {
                    console.error(`错误: 无法读取目录 ${zoom}/${x} 内容: ${error.message}`);
                    continue;
                }
                
                // 处理每个图片文件
                for (const yFile of yFiles) {
                    const yFilePath = path.join(xPath, yFile);
                    const y = path.parse(yFile).name; // 获取不带扩展名的文件名作为y值
                    
                    // 处理图片，添加文字标记
                    const success = await addTileInfoToImage(yFilePath, zoom, x, y);
                    if (success) {
                        processedCount++;
                    } else {
                        failedCount++;
                    }
                    
                    // 每处理100张图片或处理完当前批次时显示进度
                    if (processedCount % 100 === 0 || (processedCount + failedCount) % 500 === 0) {
                        const elapsedTime = (Date.now() - startTime) / 1000;
                        const rate = processedCount / elapsedTime;
                        console.log(`已处理 ${processedCount} 张图片，失败 ${failedCount} 张，处理速度: ${rate.toFixed(2)} 张/秒`);
                    }
                }
            }
        }
        
        const elapsedTime = (Date.now() - startTime) / 1000;
        console.log(`\n处理完成!`);
        console.log(`总处理图片数: ${processedCount + failedCount}`);
        console.log(`成功: ${processedCount} 张`);
        console.log(`失败: ${failedCount} 张`);
        console.log(`耗时: ${elapsedTime.toFixed(2)} 秒`);
        console.log(`平均处理速度: ${((processedCount + failedCount) / elapsedTime).toFixed(2)} 张/秒`);
        
        return failedCount === 0;
    } catch (error) {
        console.error(`严重错误: 处理过程中发生异常: ${error.message}`);
        console.error(error.stack);
        return false;
    }
}

/**
 * 给图片添加瓦片信息文字
 * @returns {boolean} 处理是否成功
 */
async function addTileInfoToImage(imagePath, zoom, x, y) {
    try {
        // 检查文件是否存在
        if (!fs.existsSync(imagePath)) {
            console.error(`错误: 文件不存在: ${imagePath}`);
            return false;
        }
        
        // 构建要添加的文字内容 (Z/X/Y)
        const text = `${zoom}/${x}/${y}`;
        
        // 获取图片信息，以确定适合的文字大小
        let imageInfo;
        try {
            imageInfo = await sharp(imagePath).metadata();
        } catch (error) {
            console.error(`错误: 无法读取图片信息 ${imagePath}: ${error.message}`);
            return false;
        }
        
        // 根据图片宽度动态调整文字大小和背景高度
        const imageWidth = imageInfo.width || 256;
        const fontSize = Math.max(16, Math.min(48, Math.floor(imageWidth / 10)));
        const backgroundHeight = Math.max(60, Math.floor(fontSize * 2));
        
        // 创建临时文件路径
        const tempFilePath = `${imagePath}.temp`;
        
        // 使用sharp处理图片，先输出到临时文件
        try {
            await sharp(imagePath)
                .composite([{
                    input: Buffer.from(`<svg width="${imageWidth}" height="${backgroundHeight}" xmlns="http://www.w3.org/2000/svg">
                        <!-- 移除背景矩形，只保留红色文字 -->
                        <text x="50%" y="50%" font-family="Arial" font-size="${fontSize}" font-weight="bold" fill="red" text-anchor="middle" dominant-baseline="middle">${text}</text>
                    </svg>`),
                    gravity: 'north'
                }])
                .toFile(tempFilePath);
        } catch (error) {
            // 清理临时文件
            if (fs.existsSync(tempFilePath)) {
                fs.unlinkSync(tempFilePath);
            }
            throw error;
        }
        
        // 重命名临时文件为原始文件
        try {
            // 在Windows上，需要先删除目标文件
            if (fs.existsSync(imagePath)) {
                fs.unlinkSync(imagePath);
            }
            fs.renameSync(tempFilePath, imagePath);
        } catch (error) {
            // 清理临时文件
            if (fs.existsSync(tempFilePath)) {
                fs.unlinkSync(tempFilePath);
            }
            throw error;
        }
            
        return true;
            
    } catch (error) {
        console.error(`处理图片失败 ${imagePath}: ${error.message}`);
        return false;
    }
}

/**
 * 主函数
 */
async function main() {
    console.log('========================================');
    console.log('瓦片图片标记工具 v1.0');
    console.log('功能: 在XYZ瓦片图片上添加路径信息');
    console.log('========================================');
    
    try {
        // 检查依赖
        if (!checkDependencies()) {
            console.log('\n请安装依赖后再运行此工具');
            process.exit(1);
        }
        
        // 解析命令行参数
        const options = parseArguments();
        
        // 显示帮助信息
        if (options.help || !options.input) {
            showHelp();
            process.exit(options.help ? 0 : 1);
        }
        
        // 规范化输入路径
        const inputDir = path.resolve(options.input);
        console.log(`输入目录: ${inputDir}`);
        
        // 处理瓦片目录
        console.log('\n开始处理瓦片图片...');
        const startTime = Date.now();
        const success = await processTileDirectory(inputDir);
        const totalTime = (Date.now() - startTime) / 1000;
        
        console.log(`\n总耗时: ${totalTime.toFixed(2)} 秒`);
        
        if (success) {
            console.log('任务成功完成!');
            process.exit(0);
        } else {
            console.log('任务部分失败，请查看日志了解详情');
            process.exit(1);
        }
    } catch (error) {
        console.error('\n严重错误: 程序执行异常');
        console.error(error.message);
        console.error(error.stack);
        process.exit(2);
    }
}

// 执行主函数
main().catch(error => {
    console.error('发生错误:', error.message);
    process.exit(1);
});

// 导出函数以便其他模块使用
module.exports = {
    processTileDirectory,
    addTileInfoToImage
};